home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC Media 22
/
PC MEDIA CD22.iso
/
share
/
prog
/
datalib2
/
database.cpp
next >
Wrap
C/C++ Source or Header
|
1995-08-15
|
6KB
|
300 lines
#include "datapriv.hpp"
/*************** DATABASE ACCESSOR FUNCTIONS ***************/
// Get pointer to index by name, return 0 if not found
index *database::getindex(char *name)
{
if (!findex) return 0;
index *ip=findex;
while(ip && strcmpl(ip->name,name)) ip=ip->next;
return ip;
}
char *database::getindkey(char *name)
{
index *ip;
if (ip=getindex(name)) return(ip->indexp);
return 0;
}
int database::getindtype(char *name)
{
index *ip;
if (ip=getindex(name)) return(ip->indtype);
return 0;
}
/*************** DATABASE FUNCTIONS ************************/
// This is the constructor for a database
// it opens the file and initialises the database variables.
/*************** CONSTRUCTOR *******************************/
// This is the constructor for a new database
database::database()
{
valid=-1;
ex=0;
exwork=0;
dbtp=0;
memowl=0;
memow=0;
firstrec=0;
change=1;
findex=0;
dbfp=0;
nrec=0;
nfield=0;
maxfieldl=0;
reclen=1;
findex=0;
dateformat=USDATE;
if (!(fielda=new field*[MAXFLD])) {dbfer(NODBSP); valid=NOMEM;}
}
// This is the constructor for an existing database
database::database(char *name,char *index)
{
char n[128],ws[128],*wsp;
int i;
int recpos=1;
valid=0;
ex=0; // Start with no expression evaluator
exwork=0;
dbtp=0;
memowl=0;
memow=0;
firstrec=0;
change=0;
findex=0;
dateformat=USDATE;
if (!(fielda=new field*[MAXFLD])) {dbfer(NODBSP); valid=NOMEM; return;}
strcpy(n,name);
if (!strchr(n,'.')) strcat(n,".dbf");
if (!(dbfp=fopen(n,"r+b"))) {valid=NOFILE; return;}
Fread(ws,DBSIZE,1,dbfp); // Get database file statistics
if (*ws&0x80)
{
*(strchr(n,'.'))=0; strcat(n,".dbt");
dbtp=fopen(n,"r+b");
if (!dbtp) {valid=MEMOERR; return;}
}
nrec=*(long *)(ws+4); // Now get the file parameters
recstart=*(int *)(ws+8);
reclen=*(int *)(ws+10);
nfield=0; maxfieldl=0;
do // Count number of fields
{
fielda[nfield]=0;
Fread(ws,DBSIZE,1,dbfp);
if (*ws==0x0d) break;
nfield++;
}
while(!feof(dbfp));
Fseek(dbfp,0L,SEEK_SET);
Fread(ws,DBSIZE,1,dbfp);
for(i=0; i<nfield; i++) // Read all field information
{
int flen; // Field length
Fread(ws,DBSIZE,1,dbfp);
flen=(unsigned char)ws[16];
if (!(fielda[i]=new field(i+1,ws,ws[11],flen,
(unsigned char)ws[17],recpos)))
{dbfer(NODBSP); valid=NOMEM; return;}
recpos=recpos+flen;
if (flen>maxfieldl) maxfieldl=flen;
}
// Now open the index file
if (!index || !(*index)) return;
valid=addindex(index);
}
/*************** DESTRUCTOR ********************************/
// This is the destructor for a database object.
database::~database(void)
{
int i;
class field *temp;
if (dbfp)
{
if (change)
{
struct tm *t;
time_t ltime;
time(<ime); t=localtime(<ime);
Fseek(dbfp,1L,SEEK_SET);
Fputc(t->tm_year,dbfp);
Fputc(t->tm_mon+1,dbfp);
Fputc(t->tm_mday,dbfp);
fputl(nrec,dbfp);
}
fclose(dbfp);
for(i=0; i<nfield; i++) if (fielda[i]) delete fielda[i];
}
index *ip=findex;
index *nip;
while(ip) {nip=ip; ip=ip->next; delete nip;} // Close all the indexes
if (fielda) delete fielda;
if (ex) delete ex;
if (exwork) delete exwork;
if (memow) delete memow;
if (dbtp) fclose(dbtp);
if (firstrec) dber(DELREC); // Cannot delete database with attached rec.s
}
/*************** GETFIELD *******************************/
// This function searches for a field by name and returns a pointer
field *database::getfield(char *fname)
{
for (int i=0; i<nfield; i++)
{
if (!strcmpl(fielda[i]->name,fname)) return(fielda[i]);
}
return(0);
}
/*************** Add a field to a fresh database ********/
// This version copies a field from elsewhere
int database::addfield(field *fp)
{
if (valid>=0) return INVFIELD;
int i;
for(i=0; i<nfield; i++)
if (!strcmpi(fielda[i]->name,fp->name)) return DUPFIELD;
nfield++;
fielda[nfield-1]=new field(nfield,fp->name,fp->type,fp->len,fp->rdp,reclen);
reclen+=fp->len;
if (fp->len>maxfieldl) maxfieldl=fp->len;
if (fp->type) valid=-2;
return 0;
}
// This version adds a completely new field
int database::addfield(char *name,int type,int len,int rdp)
{
if (valid>=0) return INVFIELD;
int i;
for(i=0; i<nfield; i++)
if (!strcmpi(fielda[i]->name,name)) return DUPFIELD;
int ln=len;
if (ln<1) return INVFIELD;
switch(type&0xdf)
{
case 'C' : break;
case 'D' : ln=8; break;
case 'L' : ln=1; break;
case 'M' : valid=-2; ln=10; break;
case 'N' : if (rdp<0 || rdp>len-2) return INVFIELD; break;
default : return INVFIELD;
}
nfield++;
fielda[nfield-1]=new field(nfield,name,type,ln,rdp,reclen);
reclen+=ln;
if (ln>maxfieldl) maxfieldl=ln;
return 0;
}
/*************** Write a database to disk ****************/
int database::write(char *name)
{
if (valid>=0 || !nfield) return NOFILE;
char n[128],ws[512],*wsp;
int i;
strcpy(n,name); if (!strchr(n,'.')) strcat(n,".dbf");
if (!(dbfp=fopen(n,"w+b"))) {valid=NOFILE; return NOFILE;}
if (valid==-2)
{
*(strchr(n,'.'))=0; strcat(n,".dbt");
dbtp=fopen(n,"w+b");
if (!dbtp) {valid=MEMOERR; return MEMOERR;}
memset(ws,0,512);
*ws=1;
sprintf(ws+16,"Memo File written by dBase Library, Robin Abbott, %s",name);
Fwrite(ws,512,1,dbtp);
}
memset(ws,0,32);
*ws=(dbtp) ? 0x83 : 0x03;
recstart=32*(nfield+1)+1;
*(int *)(ws+8)=recstart;
*(int *)(ws+10)=reclen;
Fwrite(ws,32,1,dbfp);
for(i=0; i<nfield; i++)
{
memset(ws,0,32);
strcpy(ws,fielda[i]->name);
ws[11]=fielda[i]->type;
ws[16]=fielda[i]->len;
ws[17]=fielda[i]->rdp;
Fwrite(ws,32,1,dbfp);
}
Fputc(0x0d,dbfp);
valid=0;
return 0;
}
/*****************************************
Here come a number of utility routines
******************************************/
void fputl(long l,FILE *fp)
{
fputc(l&0xff,fp);
fputc((l>>8) & 0xff,fp);
fputc((l>>16) & 0xff,fp);
fputc((l>>24) & 0xff,fp);
}